﻿#include "ReadN.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iostream>

using namespace std;

ReadN::ReadN() { }

ReadN::ReadN(string filePath) {
    this->filePath = filePath;
}

bool ReadN::set_file(string filePath) {
    this->filePath = filePath;
    return true;
}

bool ReadN::parseFile() {
    ifstream file(filePath);
    if (!file.is_open()) {
        cerr << "Error: Cannot open file " << filePath << endl;
        return false;
    }
    string line;
    bool isHeaderEnd = false;
    // 阶段1：解析文件头
    while (getline(file, line)) {
        if (line.find("END OF HEADER") != string::npos) {
            isHeaderEnd = true;
            break;
        }
        parseHeaderLine(line);
    }
    // 阶段2：解析星历数据
    if (isHeaderEnd) {
        BroadEphemeris currentEph;
        while (getline(file, line)) {
            if (line.empty()) continue;
            if (line[0] == 'C') { // 新卫星数据块
                if (!currentEph.prn.empty()) {
                    ListBroadEph.push_back(currentEph);
                }
                currentEph = parseEpochLine(line);
            }
            else { // 参数行
                parseDataLine(line, currentEph);
            }
        }
        ListBroadEph.push_back(currentEph); // 添加最后一个星历
    }
    file.close();
    return true;
}

// 解析文件头单行
void ReadN::parseHeaderLine(string& line) {
    string label = line.substr(60, 20);

    if (label.find("RINEX VERSION") != string::npos) {
        header.version = line.substr(0, 20);
    }
    else if (label.find("PGM / RUN BY") != string::npos) {
        istringstream iss(line.substr(0, 60));
        iss >> header.creatingProgram >> header.creatingAgency >> header.creationDate;
    }
    else if (label.find("LEAP SECONDS") != string::npos) {
        header.leapSeconds = stoi(line.substr(0, 6));
    }
    else if (label.find("IONOSPHDRIC CORR") != string::npos) {
        string prefix = line.substr(0, 4);
        if (prefix == "COMA") {
            for (int i = 0; i < 4; ++i) {
                string val = line.substr(5 + i * 12, 12);
                replace(val.begin(), val.end(), 'D', 'E');
                header.ionAlpha[i] = stod(val);
            }
        }
        else if (prefix == "COMB") {
            for (int i = 0; i < 4; ++i) {
                string val = line.substr(5 + i * 12, 12);
                replace(val.begin(), val.end(), 'D', 'E');
                header.ionBeta[i] = stod(val);
            }
        }
    }
}

// 解析星历头行
BroadEphemeris ReadN::parseEpochLine(string& line) {
    BroadEphemeris eph;
    eph.prn = line.substr(0, 3);
    eph.year = stoi(line.substr(4, 4));
    eph.month = stoi(line.substr(9, 2));
    eph.day = stoi(line.substr(12, 2));
    eph.hour = stoi(line.substr(15, 2));
    eph.min = stoi(line.substr(18, 2));
    eph.sec = stod(line.substr(21, 19));
    // 解析钟差参数
    for (int i = 0; i < 3; ++i) {
        int startPos = 23 + i * 19;
        string tmp = line.substr(startPos, 19);
        replace(tmp.begin(), tmp.end(), 'D', 'E');
        if (i == 0) eph.clockBias = stod(tmp);
        else if (i == 1) eph.clockDrift = stod(tmp);
        else if (i == 2) eph.clockDriftRate = stod(tmp);
    }
    return eph;
}

// 解析数据行
void ReadN::parseDataLine(string& line, BroadEphemeris& eph) {
    for (int i = 0; i < 4; ++i) {
        int pos = 4 + i * 19;
        if (pos + 19 > line.length()) break;
        string val = line.substr(pos, 19);
        if (val.find_first_not_of(' ') == string::npos) continue;
        replace(val.begin(), val.end(), 'D', 'E');
        eph.params.push_back(stod(val));
    }
}

RinexHead& ReadN::get_head()
{
    return header;
}

BroadEphemeris* ReadN::getEphemeris(string prn, BaseT time)
{
    // 静态变量用于返回引用，防止返回局部变量引用
    static BroadEphemeris dummy;
    // 查找所有该prn的星历
    BroadEphemeris* best = nullptr;
    double minDiff = std::numeric_limits<double>::max();

    for (auto& eph : ListBroadEph) {
        if (eph.prn != prn) continue;
        // 计算星历时间（秒）
        struct tm t = { 0 };
        t.tm_year = eph.year - 1900;
        t.tm_mon = eph.month - 1;
        t.tm_mday = eph.day;
        t.tm_hour = eph.hour;
        t.tm_min = eph.min;
        t.tm_sec = static_cast<int>(eph.sec);
        time_t eph_time = mktime(&t);
        double eph_sec = static_cast<double>(eph_time) + (eph.sec - static_cast<int>(eph.sec));

        // 计算时间差
        double req_sec = static_cast<double>(time.sec) + time.sesec;
        double diff = std::abs(eph_sec - req_sec);

        if (diff < minDiff) {
            minDiff = diff;
            best = &eph;
        }
    }
    if (best) return best;
    return nullptr;
}

bool ReadN::print_eph()
{
    cout << "/* ReadN测试结果 */" << endl;
    cout << "广播星历数量： " << ListBroadEph.size() << endl;
    for (int i = 0; i < 1 && i < this->ListBroadEph.size(); ++i) {
        const auto& eph = this->ListBroadEph[i];
        cout << "卫星 " << eph.prn << "" << endl;
        // 时间信息（保持不变）
        cout << "│ 历元时间: " << eph.year << "-"
            << setw(2) << setfill('0') << eph.month << "-"
            << setw(2) << eph.day << " "
            << setw(2) << eph.hour << ":"
            << setw(2) << eph.min << ":"
            << fixed << setprecision(2) << eph.sec << endl;
        // 钟差参数（保持不变）
        cout << "卫星钟差数据\n";
        cout << scientific << setprecision(12)
            << "│   钟差(a0): " << setw(19) << eph.clockBias
            << "│   钟速(a1): " << setw(19) << eph.clockDrift
            << "│ 钟速变化率(a2): " << setw(19) << eph.clockDriftRate << endl;
        // 轨道参数详细显示
        cout << "轨道参数数据\n";
        for (int i = 0; i < eph.params.size(); ++i) {
            cout << "│ " << scientific << setw(19) << eph.params[i];
            if ((i + 1) % 4 == 0)  cout << endl;// 每行显示4个参数
        }
        cout << endl;
    }
    cout << endl;
    return true;
}